package com.javatest.springbootquartz.util;

import com.javatest.springbootquartz.entity.AppOnce;
import com.javatest.springbootquartz.entity.AppQuartz;
import org.quartz.*;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Qualifier;
import org.springframework.stereotype.Service;

import java.text.ParseException;
import java.text.SimpleDateFormat;
import java.util.Date;

/**
 * Created with IntelliJ IDEA.
 * Description:
 *
 * @author liuziyang
 * @create 2019-07-02 22:33
 */
@Service
public class JobUtil {
    @Autowired
    @Qualifier("dbScheduler")
    private Scheduler dbScheduler;

    @Autowired
    @Qualifier("ramScheduler")
    private Scheduler ramScheduler;

    private static final String DATETIME_PATTERN = "yyyy-MM-dd HH:mm:ss";
    private static ThreadLocal<SimpleDateFormat> simpleDateFormat = ThreadLocal.withInitial(() -> new SimpleDateFormat(DATETIME_PATTERN));

    /**
     * 新建一个任务
     */
    public String addJob(AppQuartz appQuartz) throws Exception {
        Date date = simpleDateFormat.get().parse(appQuartz.getStartTime());
        if (!CronExpression.isValidExpression(appQuartz.getCronExpression())) {
            //表达式格式不正确
            return "Illegal cron expression";
        }
        JobDetail jobDetail = null;
        //构建job信息
        jobDetail = JobBuilder.newJob(appQuartz.getJobClass())
                .withIdentity(appQuartz.getJobName(), appQuartz.getJobGroup())
                .build();
        //表达式调度构建器(即任务执行的时间,不立即执行)
        CronScheduleBuilder scheduleBuilder = CronScheduleBuilder.cronSchedule(appQuartz.getCronExpression())
                .withMisfireHandlingInstructionDoNothing();

        //按新的cronExpression表达式构建一个新的trigger
        CronTrigger trigger = TriggerBuilder.newTrigger()
                .withIdentity(appQuartz.getJobName(), appQuartz.getJobGroup())
                .startAt(date)
                .withSchedule(scheduleBuilder)
                .build();

        //传递参数
        if (appQuartz.getInvokeParam() != null && !"".equals(appQuartz.getInvokeParam())) {
            trigger.getJobDataMap().put("invokeParam", appQuartz.getInvokeParam());
        }

        //使用调度器调度
        dbScheduler.scheduleJob(jobDetail, trigger);
        return "success";
    }

    public String addJob(AppOnce appOnce) throws ParseException, SchedulerException {
        JobDetail jobDetail = JobBuilder.newJob(appOnce.getJobClass())
                .withIdentity(appOnce.getJobName(), appOnce.getJobGroup())
                .build();

        Date date = simpleDateFormat.get().parse(appOnce.getExecuteTime());
        // 配置只执行一次的触发器
        SimpleTrigger trigger = (SimpleTrigger) TriggerBuilder.newTrigger()
                .withIdentity(appOnce.getJobName(), appOnce.getJobGroup())
                .startAt(date)
                .build();
        if (appOnce.getInvokeParam() != null && !"".equals(appOnce.getInvokeParam())) {
            trigger.getJobDataMap().put("invokeParam", appOnce.getInvokeParam());
        }
        ramScheduler.scheduleJob(jobDetail, trigger);
        return "success";
    }

    /**
     * 获取Job状态
     *
     * @param jobName
     * @param jobGroup
     * @return
     * @throws SchedulerException
     */
    public String getJobState(String jobName, String jobGroup) throws SchedulerException {
        TriggerKey triggerKey = new TriggerKey(jobName, jobGroup);
        return dbScheduler.getTriggerState(triggerKey).name();
    }

    //暂停所有任务
    public void pauseAllJob() throws SchedulerException {
        dbScheduler.pauseAll();
    }

    //暂停任务
    public String pauseJob(String jobName, String jobGroup) throws SchedulerException {
        JobKey jobKey = new JobKey(jobName, jobGroup);
        JobDetail jobDetail = dbScheduler.getJobDetail(jobKey);
        if (jobDetail == null) {
            return "fail";
        } else {
            dbScheduler.pauseJob(jobKey);
            return "success";
        }
    }

    //恢复所有任务
    public void resumeAllJob() throws SchedulerException {
        dbScheduler.resumeAll();
    }

    // 恢复某个任务
    public String resumeJob(String jobName, String jobGroup) throws SchedulerException {
        JobKey jobKey = new JobKey(jobName, jobGroup);
        JobDetail jobDetail = dbScheduler.getJobDetail(jobKey);
        if (jobDetail == null) {
            return "fail";
        } else {
            dbScheduler.resumeJob(jobKey);
            return "success";
        }
    }

    //删除某个任务
    public String deleteJob(AppQuartz appQuartz) throws SchedulerException {
        JobKey jobKey = new JobKey(appQuartz.getJobName(), appQuartz.getJobGroup());
        JobDetail jobDetail = dbScheduler.getJobDetail(jobKey);
        if (jobDetail == null) {
            return "jobDetail is null";
        } else if (!dbScheduler.checkExists(jobKey)) {
            return "jobKey is not exists";
        } else {
            dbScheduler.deleteJob(jobKey);
            return "success";
        }
    }

    public String deleteJob(AppOnce appOnce) throws SchedulerException {
        JobKey jobKey = new JobKey(appOnce.getJobName(), appOnce.getJobGroup());
        JobDetail jobDetail = ramScheduler.getJobDetail(jobKey);
        if (jobDetail == null) {
            return "jobDetail is null";
        } else if (!ramScheduler.checkExists(jobKey)) {
            return "jobKey is not exists";
        } else {
            ramScheduler.deleteJob(jobKey);
            return "success";
        }
    }

    //修改任务
    public String modifyJob(AppQuartz appQuartz) throws SchedulerException {
        if (!CronExpression.isValidExpression(appQuartz.getCronExpression())) {
            return "Illegal cron expression";
        }
        TriggerKey triggerKey = TriggerKey.triggerKey(appQuartz.getJobName(), appQuartz.getJobGroup());
        JobKey jobKey = new JobKey(appQuartz.getJobName(), appQuartz.getJobGroup());
        if (dbScheduler.checkExists(jobKey) && dbScheduler.checkExists(triggerKey)) {
            CronTrigger trigger = (CronTrigger) dbScheduler.getTrigger(triggerKey);
            //表达式调度构建器,不立即执行
            CronScheduleBuilder scheduleBuilder = CronScheduleBuilder.cronSchedule(appQuartz.getCronExpression()).withMisfireHandlingInstructionDoNothing();
            //按新的cronExpression表达式重新构建trigger
            trigger = trigger.getTriggerBuilder().withIdentity(triggerKey)
                    .withSchedule(scheduleBuilder).build();
            //修改参数
            if (!trigger.getJobDataMap().get("invokeParam").equals(appQuartz.getInvokeParam())) {
                trigger.getJobDataMap().put("invokeParam", appQuartz.getInvokeParam());
            }
            //按新的trigger重新设置job执行
            dbScheduler.rescheduleJob(triggerKey, trigger);
            return "success";
        } else {
            return "job or trigger not exists";
        }
    }

}